package com.yjzx.care;

import com.yjzx.care.base.BaseElement;
import com.yjzx.care.base.Element;
import com.yjzx.care.base.ValueGet;
import com.yjzx.care.base.ValueGetSet;

import java.util.function.BooleanSupplier;
import java.util.function.Supplier;

/**
 * @author yjzx
 * @date 2023/12/25
 * @description 有返回值的判断
 */
public final class ElementReturn<T> extends BaseElement implements ValueGetSet<T> {
    public interface ElseReturn<T> extends Else, ValueGet<T> {
        /**
         * 最后的else
         *
         * @param supplier 运行方法
         * @return 返回运算结果接口
         */
        default ValueGet<T> otherwise(Supplier<T> supplier) {
            return this;
        }

        /**
         * if else
         *
         * @param whether  判断
         * @param supplier 运行方法
         * @return 返回else接口
         */
        default ElseReturn<T> otherwise(boolean whether, Supplier<T> supplier) {
            return this;
        }

        default ElseReturn<T> otherwise(BooleanSupplier whether, Supplier<T> supplier) {
            return this;
        }
    }

    private final ElseReturn<T> defaultElse = new ElseReturn<T>() {
        @Override
        public T get() {
            return value;
        }

        @Override
        public ElseReturn<T> otherwise(Supplier<T> supplier) {
            return ifExist(true, supplier);
        }

        @Override
        public ElseReturn<T> otherwise(boolean whether, Supplier<T> supplier) {
            return ifExist(whether, supplier);
        }

        @Override
        public ElseReturn<T> otherwise(BooleanSupplier whether, Supplier<T> supplier) {
            return ifExist(isWhether() && whether.getAsBoolean(), supplier);
        }

    };
    private final ElseReturn<T> noopElse = new ElseReturn<T>() {
        @Override
        public T get() {
            return value;
        }
    };
    private volatile T value;

    ElementReturn() {
    }

    /**
     * 进行判断，是否执行
     *
     * @param whether  判断
     * @param supplier true执行的代码
     * @return
     */
    public ElseReturn<T> ifExist(boolean whether, Supplier<T> supplier) {
        if (whether && this.exist(whether)) {
            this.value = supplier.get();
            return noopElse;
        }
        return isWhether() ? this.defaultElse : this.noopElse;
    }

    @Override
    public T get() {
        return this.value;
    }

    @Override
    public void set(T value) {
        this.value = value;
    }

    public final static class ElementReturnBuilder<T> implements MyInterface {
        ElementReturnBuilder() {
        }

        public ReturnElseBuilder<T> ifExistToBuilder(boolean whether, Supplier<T> supplier) {
            Supplier<T> value = null;
            if (whether) {
                value = supplier;
            }
            return new ReturnElseBuilder<>(value);
        }

        @SafeVarargs
        public final ReturnElseBuilder<T> returnBuilder(Element<Supplier<T>>... elements) {
            Supplier<T> value = null;
            for (Element<Supplier<T>> element : elements) {
                if ((value = element.getValue()) != null) {
                    break;
                }
            }
            return new ReturnElseBuilder<>(value);
        }

        public static class ReturnElseBuilder<T> {
            private volatile Supplier<T> supplier;
            private volatile boolean flag = true;

            public ReturnElseBuilder(Supplier<T> supplier) {
                this.supplier = supplier;
            }

            public synchronized ReturnElseBuilder<T> otherwise(boolean whether, Supplier<T> supplier) {
                if (this.supplier != null && whether) {
                    this.supplier = supplier;
                }
                return this;
            }

            public synchronized ReturnElseBuilder<T> otherwise(BooleanSupplier whether, Supplier<T> supplier) {
                if (this.supplier != null && whether.getAsBoolean()) {
                    this.supplier = supplier;
                }
                return this;
            }

            public synchronized ReturnElseBuilder<T> otherwise(Supplier<T> supplier) {
                synchronized (this) {
                    if (this.supplier != null) {
                        this.supplier = supplier;
                    }
                    return this;
                }
            }

            public synchronized ElseReturn<T> otherwiseBuild(Supplier<T> supplier) {
                synchronized (this) {
                    if (this.supplier != null) {
                        this.supplier = supplier;
                    }
                    return build();
                }
            }

            public synchronized ElseReturn<T> build() {
                if (this.flag) {
                    this.flag = false;
                    ElseReturn<T> t;
                    if (this.supplier != null) {
                        T t1 = this.supplier.get();
                        t = () -> t1;
                        this.supplier = null;
                    } else {
                        t = new ElementReturn<T>().defaultElse;
                    }
                    this.flag = true;
                    return t;
                } else {
                    throw new IllegalStateException("Exist or Builder can only be used once.");
                }
            }
        }
    }
}